using System.Collections.Generic;
using System.Linq;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;

namespace uMVP.Dialog
{
    public interface IModelDialog
    {
        /// <summary>
        /// 打开模态对话框， 如果前一个模态对话框还存在，则OpenAsync会一直阻塞
        /// </summary>
        /// <returns></returns>
        UniTask OpenAsync();

        /// <summary>
        /// 关闭模态对话框
        /// </summary>
        /// <returns></returns>
        UniTask CloseAsync();
    }

    /// <summary>
    /// 模态对话框基类（所谓模态对话框就是同一个时间只能存在一个，且其他非模态对话框不能响应事件）
    /// </summary>
    public abstract class ModelDialogBase : IModelDialog
    {
        private bool _isOpen;
        protected readonly Canvas Canvas;

        protected ModelDialogBase()
        {
            var canvasObject = new GameObject("ModelDialogCanvas");
            Canvas = canvasObject.AddComponent<Canvas>();
            Canvas.renderMode = RenderMode.ScreenSpaceOverlay;
            Canvas.gameObject.layer = 5;
            Canvas.sortingOrder = 10000;
            canvasObject.AddComponent<CanvasScaler>();
            canvasObject.AddComponent<GraphicRaycaster>();
        }

        public async UniTask OpenAsync()
        {
            await UniTask.WaitUntil(() => _isOpen == false);
            _isOpen = true;
            SetCanvasListEnabled(false);
            await OnOpenAsync();
        }

        public async UniTask CloseAsync()
        {
            _isOpen = false;
            SetCanvasListEnabled(true);
            await OnCloseAsync();
        }

        private void SetCanvasListEnabled(bool enabled)
        {
            //return;
            // var canvasList = FindOtherCanvas();
            // foreach (var canvas in canvasList)
            // {
            //     var raycaster = canvas.gameObject.GetComponent<GraphicRaycaster>();
            //     if (raycaster != null)
            //         raycaster.enabled = enabled;
            // }
        }

        private IEnumerable<Canvas> FindOtherCanvas()
        {
            var canvasList = Object.FindObjectsOfType<Canvas>();
            return canvasList.Where(canvas => canvas != Canvas);
        }

        protected abstract UniTask OnOpenAsync();
        protected abstract UniTask OnCloseAsync();
    }
}